<template>
  <div class="pagesTable">
    <div class="table">
      <el-table
        ref="tableRef"
        :data="tableData"
        v-bind="_options"
        @select="handleSelectionChange"
        @select-all="handleSelectionAl"
        @row-click="handleRowClick"
        @cell-click="handleCellClick"
        @sort-change="handleSortChange"
      >
        <template v-for="col in columns">
          <!--- 序号、复选框 -->
          <template v-if="col.type === 'index' || col.type === 'selection'">
            <el-table-column v-bind="col" :index="indexMethod" />
          </template>
          <!-- 渲染插槽 START -->
          <template v-else>
            <TableColumn :col="col" @command="handleAction">
              <template
                v-for="slot in Object.keys($slots)"
                #[slot]="scope: Record<string, any>"
              >
                <slot :name="slot" v-bind="scope" />
              </template>
            </TableColumn>
          </template>
        </template>
      </el-table>
    </div>
    <!-- 分页器 -->
    <div v-if="_options.showPagination" class="paginationBox">
      <Pagination
        :pageConfig="_options.paginationConfig"
        @pagination-change="paginationChange"
        @size-change="sizeChange"
        @current-change="currentChange"
      ></Pagination>
    </div>
  </div>
</template>
<script lang="ts" setup>
import type { ComputedRef } from 'vue';
import TableColumn from './TableColumn.vue';

// 父组件传递数据
const props = defineProps({
  columns: {
    type: Array,
  },
  tableData: {
    type: Array,
  },
  options: {
    type: Object,
  },
});

// 设置option默认值，如果传入自定义的配置则合并option配置项
const _options: ComputedRef<Table.Options> = computed(() => {
  const option = {
    stripe: false,
    border: true,
    height: '100%',
    maxHeight: '100%',
    tooltipEffect: 'dark',
    showHeader: true,
    showPagination: false,
    showOverflowTooltip: true,
    rowStyle: () => 'cursor:pointer',
    rowKey: 'id',
    defaultExpandAll: false,
    // 改变表头背景颜色
    headerCellStyle: () => ({
      background: '#e9f2fa',
    }),
  };
  return Object.assign(option, props?.options);
});

// 自定义(序号索引)
const indexMethod = (index: number) => {
  const tabIndex = props.options.showPagination
    ? index +
      (props.options.paginationConfig.currentPage - 1) *
        props.options.paginationConfig.pageSize +
      1
    : index + 1;
  return tabIndex;
};

// 定义暴露事件名
const emit = defineEmits([
  'selection-change', // 当选择项发生变化时会触发该事件
  'row-click', // 当某一行被点击时会触发该事件
  'cell-click', // 当某个单元格被点击时会触发该事件
  'command', // 按钮组事件
  'handel-size-change', // pageSize事件
  'handel-current-change', // currentPage按钮组事件
  'handel-pagination-change', // currentPage或者pageSize改变触发
  'sort-change', // 列排序发生改变触发
  'selection-all', // 全选
]);

// 切换pageSize
const sizeChange = (pageSize: number) => {
  emit('handel-size-change', pageSize);
};

// 切换currentPage
const currentChange = (currentPage: number) => {
  emit('handel-current-change', currentPage);
};

// 切换currentPage或切换pageSize都可以触发
const paginationChange = (currentPage: number, pageSize: number) => {
  emit('handel-pagination-change', currentPage, pageSize);
};

// 按钮组事件
const handleAction = (command: Table.Command, row: any, index: number) => {
  emit('command', command, row, index);
};

// 多选事件
const handleSelectionChange = (val: any, row: any) => {
  emit('selection-change', val, row);
};
// 全选
const handleSelectionAl = (val: any) => {
  emit('selection-all', val);
};

// 当某一行被点击时会触发该事件
const handleRowClick = (row: any, column: any, event: MouseEvent) => {
  emit('row-click', row, column, event);
};

// 当某个单元格被点击时会触发该事件
const handleCellClick = (
  row: any,
  column: any,
  cell: any,
  event: MouseEvent,
) => {
  emit('cell-click', row, column, cell, event);
};

/**
 *  当表格的排序条件发生变化的时候会触发该事件
 * 在列中设置 sortable 属性即可实现以该列为基准的排序， 接受一个 Boolean，默认为 false。
 * 可以通过 Table 的 default-sort 属性设置默认的排序列和排序顺序。
 * 如果需要后端排序，需将 sortable 设置为 custom，同时在 Table 上监听 sort-change 事件，
 * 在事件回调中可以获取当前排序的字段名和排序顺序，从而向接口请求排序后的表格数据。
 */
const handleSortChange = ({ column, prop, order }) => {
  emit('sort-change', column, prop, order);
};

/**
 * 将组件的内部属性、方法暴露给父组件的函数
 * 使用方法例:
 *  父组件中：
    const table = ref(null);
    <Table :columns="columns" :table-data="tableData" :options="options" ref="table"></Table>
    const btn = () => {
      console.log(table.value.handleSelectionChange());
    }
  * 子组件中：
    defineExpose({
      element: tableRef,
      handleSelectionChange,
      handleRowClick,
      handleCellClick,
      handleSortChange,
    });
*/
const tableRef = ref();

// 清除表格选中
const handelClearSelection = () => {
  tableRef.value.clearSelection();
};
// 表格多选回显
const handelToggleRowSelection = (row, selected) => {
  tableRef.value.toggleRowSelection(row, selected);
};
// 重排表格
const moveDoLayout = () => {
  nextTick(() => {
    tableRef.value?.doLayout();
  });
};

defineExpose({
  element: tableRef,
  handelClearSelection: handelClearSelection,
  handelToggleRowSelection: handelToggleRowSelection,
  moveDoLayout: moveDoLayout,
});

/*********************************************** */
// demo start
// 表格组件配置
// const options = ref({
//   showPagination: true,
//   paginationConfig: {
//     total: 80,
//     currentPage: 1,
//     pageSize: 10,
//   },
// });

// // 表格columns
// const columns = ref([
//   { type: 'selection', width: '65', align: 'center' },
//   { type: 'index', width: '65', label: '序号', align: 'center' },
//   { prop: 'avatar', type: 'image', label: '图片', width: '100' },
//   { prop: 'date', type: 'date', label: '日期', width: '90', align: 'center' },
//   {
//     label: '自定义表头',
//     prop: 'headerText',
//     headerRender: ({ column }) =>
//       h(ElTag, { type: 'danger' }, () => `${column.label}(渲染函数自定义表头)`),
//   },
//   {
//     label: '多级表头',
//     headerSlot: 'deliveryHeader',
//     children: [
//       { label: 'Name', prop: 'name', width: '120' },
//       {
//         label: 'Address Info',
//         headerRender: ({ column }) =>
//           h(
//             ElTag,
//             { type: 'success' },
//             () => `${column.label}(渲染函数自定义表头)`,
//           ),
//         children: [
//           {
//             label: 'State',
//             prop: 'state',
//             width: '240',
//             headerSlot: 'stateHeader',
//           },
//           { label: 'City', prop: 'city', width: '120' },
//           {
//             label: 'Address',
//             prop: 'address',
//             headerRender: ({ column }) =>
//               h(
//                 ElTag,
//                 { type: 'warning' },
//                 () => `${column.label}(渲染函数自定义表头)`,
//               ),
//           },
//           {
//             label: 'Zip',
//             width: '120',
//             render: ({ row }) => h(ElTag, { type: 'success' }, () => row.zip),
//           },
//         ],
//       },
//     ],
//   },
//   {
//     width: '180',
//     label: '操作',
//     buttons: [
//       { name: '编辑', type: 'success', command: 'edit' },
//       { name: '删除', type: 'danger', command: 'delete' },
//     ],
//   },
// ]);

// // 获取表格数据
// const tableData = ref([]);
// demo end
</script>

<style lang="scss" scoped>
.pagesTable {
  height: 100%;
  display: flex;
  flex-direction: column;

  .table {
    flex: 1;
    height: 100%;
    overflow: hidden;
    ::v-deep .el-table {
      height: 100%;
    }
    ::v-deep .el-scrollbar__wrap {
      display: flex; // 暂无数据文案居中
    }
    ::v-deep .cell {
      justify-content: center;
      height: 32px;
      line-height: 32px;
    }
  }
  .paginationBox {
    display: flex;
    justify-content: end;
    height: 32px;
    margin-top: 20px;
  }
}
</style>
